package com.realestate.dao;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Repository;

import com.mysema.query.BooleanBuilder;
import com.mysema.query.jpa.JPQLQuery;
import com.mysema.query.jpa.JPQLSubQuery;
import com.mysema.query.jpa.impl.JPAQuery;
import com.mysema.query.types.Path;
import com.mysema.query.types.expr.BooleanExpression;
import com.realestate.constants.AppConstant;
import com.realestate.constants.ComUnitName;
import com.realestate.constants.RecordStatus;
import com.realestate.model.BrtbProduct;
import com.realestate.model.BrtbProductAttributeValue;
import com.realestate.model.QBrtbAttribute;
import com.realestate.model.QBrtbCategory;
import com.realestate.model.QBrtbProduct;
import com.realestate.model.QBrtbProductAttributeValue;
import com.trg.dao.jpa.GenericDAOImpl;

@Repository
public class ProductQueryDaoImpl extends GenericDAOImpl<BrtbProduct, Long>
		implements ProductQueryDao {

	private static final Logger logger = Logger
			.getLogger(ProductQueryDaoImpl.class);

	@Override
	@PersistenceContext(unitName = ComUnitName.COM_UNIT)
	public void setEntityManager(EntityManager entityManager) {
		super.setEntityManager(entityManager);
	}

	@Override
	public List<BrtbProduct> getListproductByCategoryCode(String categoryCode,
			Long limit) {
		JPQLQuery query = new JPAQuery(em());

		QBrtbProduct product = QBrtbProduct.brtbProduct;
		QBrtbCategory category = QBrtbCategory.brtbCategory;

		BooleanBuilder where = new BooleanBuilder();
		if (categoryCode != null && !categoryCode.equals(AppConstant.ALL)) {
			where.and(category.categoryCode.eq(categoryCode));
		}
		where.and(category.recordStatus.eq(RecordStatus.O)).and(
				product.recordStatus.eq(RecordStatus.O));

		query.from(product).leftJoin(product.brtbCategory, category)
				.where(where).orderBy(product.makeDate.desc()).limit(limit);

		List<BrtbProduct> products = query.list(product);
		return products;
	}

	@Override
	public List<BrtbProduct> getListproductByCategoryCode(String categoryCode,
			Map<String, String> filter, Long limit) {
		JPQLQuery query = new JPAQuery(em());

		QBrtbProduct product = QBrtbProduct.brtbProduct;
		QBrtbCategory category = QBrtbCategory.brtbCategory;

		BooleanBuilder where = new BooleanBuilder();
		if (categoryCode != null && !categoryCode.equals(AppConstant.ALL)) {
			where.and(category.categoryCode.eq(categoryCode));
		}
		JPQLSubQuery subQuery = new JPQLSubQuery();
		QBrtbProductAttributeValue subBrtbProductAttributeValue = new QBrtbProductAttributeValue(
				"subBrtbProductAttributeValue");
		subQuery.from(subBrtbProductAttributeValue);
		List<BooleanExpression> lstBooleanExpressions = new ArrayList<BooleanExpression>();
		for (Entry<String, String> entry : filter.entrySet()) {
			lstBooleanExpressions
					.add(subBrtbProductAttributeValue.brtbAttribute.attributeCode
							.eq(entry.getKey()).and(
									subBrtbProductAttributeValue.strValue
											.eq(entry.getValue())));
			subQuery.where(BooleanExpression.anyOf(lstBooleanExpressions
					.toArray(new BooleanExpression[lstBooleanExpressions.size()])));
		}
		where.and(product.id.in(subQuery
				.list(subBrtbProductAttributeValue.brtbProduct.id)));
		where.and(category.recordStatus.eq(RecordStatus.O)).and(
				product.recordStatus.eq(RecordStatus.O));

		QBrtbProductAttributeValue brtbProductAttributeValue = QBrtbProductAttributeValue.brtbProductAttributeValue;
		QBrtbAttribute brtbAttribute = QBrtbAttribute.brtbAttribute;
		query.from(product)
				.leftJoin(product.brtbCategory, category)
				.where(where)
				.orderBy(product.makeDate.desc())
				.limit(limit)
				.leftJoin(product.brtbProductAttributeValues,
						brtbProductAttributeValue)
				.leftJoin(brtbProductAttributeValue.brtbAttribute,
						brtbAttribute);

		List<BrtbProduct> products = query.list(product);
		return products;
	}
}
